/*---------------------------------------------------------------------
 * File name: dma_buffer.cpp
 *
 * Copyright (c) <2020-2022>, <ChenLong>
 *
 * All rights reserved.
 *
 * Author: ChenLong
 * Email: worldlong@foxmail.com
 *--------------------------------------------------------------------*/
#include <string.h>
#include "dma_buffer.hpp"
/*
*/
DMA_Buffer::DMA_Buffer(uint8_t *buffer, int len) :
    transfer_number(0),
    _buffer(buffer),
    _length(len),
    _number(0),
    _push_index(0),
    _pop_index(0)
  {}
/*
*/
int DMA_Buffer::push(uint8_t *data, int num)
{
  if(num > _length || num < 0) {
    return -1;
  }
  int residual = _length - _push_index;
  if(num > residual) { //reset
    _push_index = 0;
  }
  memcpy(_buffer + _push_index, data, num);
  _push_index += num;
  _number += num;
  return num;
}
/*
*/
int DMA_Buffer::pop(uint8_t *data, int num)
{
  if(_number == 0) {
    return 0;
  } else if(num < 0) {
    return -1;
  } 
    
  if(_push_index < _pop_index) 
  {
    int residual = _number - _push_index;
    if(residual == 0) 
    {
      _pop_index = 0;
    } 
    else if(residual < num) 
    {
      num = residual;
    } 
  }
  
  if(num > _number) 
  {
    num = _number;
  }
  memcpy(data, _buffer + _pop_index, num);
  _pop_index += num;
  _number -= num;
  return num;
}
/*
*/
uint8_t *DMA_Buffer::dma_push_start(int num)
{
  if(num > _length || num < 0) {
    return 0;
  }
  int residual = _length - _push_index;
  if(num > residual) { //reset
    _push_index = 0;
  }
  transfer_number = num;
  return _buffer + _push_index;
}
/*
*/
int DMA_Buffer::dma_push_end(int num)
{
  int residual = _length - _push_index;
  
  if(num > residual || num < 0) {
    return -1;
  }
  _push_index += num;
  _number += num;
  return num;
}
/*
*/
uint8_t *DMA_Buffer::dma_pop_start()
{
  if(_number == 0) {
    return 0;
  }
  
  if(_push_index < _pop_index)
  {
    if(_number == _push_index) 
    {
      _pop_index = 0;
      transfer_number = _number;
    } 
    else 
    {
      transfer_number = _number - _push_index;
    }
  } 
  else 
  {
    transfer_number = _number;
  }
  return _buffer + _pop_index;
}
/*
*/
int DMA_Buffer::dma_pop_end()
{
  if(_push_index < _pop_index) 
  {
    _pop_index = 0;
  } 
  else 
  {
    _pop_index += transfer_number;
  }
  _number -= transfer_number;
  return transfer_number;
}
